<?php
/**
 * search search
 * @author pandajingjing
 * @todo 支持hl和mlt参数,支持多值的or查询(bq参数)
 * @package common_lib_search
 */
abstract class search_search{

	/**
	 * 搜索引擎种类
	 * @var int
	 */
	private $_intSearchType=1;

	/**
	 * 查询默认参数
	 * @var array
	 */
	private $_arrQueryParameters=array( 
			'start'=>0,
			'rows'=>10,
			'fl'=>'*',
			'wt'=>'json',
			'sort'=>'id+desc' 
	);

	/**
	 * 且条件参数
	 * @var array
	 */
	private $_arrAndParameters=array();

	/**
	 * 或条件参数
	 * @var array
	 */
	private $_arrOrParameters=NULL;

	/**
	 * 分类统计的字段
	 * @var array
	 */
	private $_arrFacetFields=array();

	/**
	 * 且条件的比重,用于确认哪个为Q,越前面越可能为Q
	 * @var array
	 */
	protected $_arrAndParametersProportion=array();

	/**
	 * 是否调试
	 * @var boolean
	 */
	private $_bolDebug=false;

	function __construct(){	//$this->_bolDebug=APF::get_instance()->is_debug_enabled();
	}

	/**
	 * 切换搜索引擎
	 * @param int $p_intSeachType
	 */
	function switchType($p_intSeachType){
		$this->_intSearchType=$p_intSeachType;
	}

	/**
	 * 添加且条件
	 * @param string $p_strField
	 * @param string $p_strValue
	 */
	function addAndCondition($p_strField,$p_strValue){
		$p_strField=strtolower($p_strField);
		if(isset($this->_arrAndParameters[$p_strField])){
			$this->_arrAndParameters[$p_strField][]=$p_strValue;
		}else{
			$this->_arrAndParameters[$p_strField]=array( 
					$p_strValue 
			);
		}
	}

	/**
	 * 添加或条件
	 * @param string $p_strField
	 * @param string $p_strValue
	 * @param int $p_intProportion
	 */
	function addOrCondition($p_strField,$p_strValue,$p_intProportion=20){
		$p_strField=strtolower($p_strField);
		if(NULL===$this->_arrOrParameters){
			$this->_arrOrParameters=array( 
					'KEYWORD'=>$p_strValue,
					'FIELD'=>array( 
							array( 
									$p_strField,
									$p_intProportion 
							) 
					) 
			);
		}else{
			if($this->_arrOrParameters['KEYWORD']!=$p_strValue){
				$this->_arrOrParameters['KEYWORD']=$p_strValue;
				trigger_error('You change Or keyword unexpectly!!!',E_USER_WARNING);
			}
			$intCnt=count($this->_arrOrParameters['FIELD']);
			for($i=0;$i<$intCnt;++$i){
				$arrField=$this->_arrOrParameters['FIELD'][$i];
				if($arrField[0]==$p_strField){
					trigger_error('You set this field ('.$p_strField.') in Or parameter already!!!',E_USER_WARNING);
					return;
				}
			}
			$this->_arrOrParameters['FIELD'][]=array( 
					$p_strField,
					$p_intProportion 
			);
		}
	}

	/**
	 * 设置返回的开始偏移量
	 * @param int $p_intStartNum
	 */
	function setStartNum($p_intStartNum){
		$this->_setQueryParameters('start',$p_intStartNum);
	}

	/**
	 * 设置返回数量
	 * @param int $p_intCnt
	 */
	function setFetchCnt($p_intCnt){
		$this->_setQueryParameters('rows',$p_intCnt);
	}

	/**
	 * 设置排序条件
	 * @param string $p_strSort
	 */
	function setSort($p_strSort){
		$this->_setQueryParameters('sort',urlencode($p_strSort));
	}

	/**
	 * 设置返回的字段
	 * @param mix $p_mixFields
	 */
	function setFetchFields($p_mixFields){
		if(is_array($p_mixFields)){
			$this->_setQueryParameters('fl',implode(',',$p_mixFields));
		}else{
			$this->_setQueryParameters('fl',$p_mixFields);
		}
	}

	/**
	 * 设置高亮参数
	 * @param boolean $p_bolHighLight
	 */
	function setHighLight($p_bolHighLight=true){}

	/**
	 * 设置分词模式
	 */
	function setDismaxModel(){
		$this->_setQueryType('dismax');
	}

	/**
	 * 打开分类统计模式
	 */
	function setFacetModel(){
		$this->_setQueryParameters('facet','true');
	}

	/**
	 * 设置分类统计的字段
	 * @param array $p_arrFields
	 */
	function setFacetFields($p_arrFields){
		$this->_arrFacetFields=$p_arrFields;
	}

	/**
	 * 设置需要分类统计的查询
	 * @param string $p_strField
	 * @param string $p_strValue
	 */
	function setFacetQuery($p_strField,$p_strValue){
		$this->_setQueryParameters('facet.query',$p_strField.':'.$p_strValue);
	}

	/**
	 * 设置分类统计类别数量
	 * @param int $p_intCnt
	 */
	function setFacetCnt($p_intCnt){
		$this->_setQueryParameters('facet.limit',$p_intCnt);
	}

	/**
	 * 设置分类统计是否需要从多到少排序
	 * @param boolean $p_bolSort
	 */
	function setFacetSort($p_bolSort){
		$this->_setQueryParameters('facet.sort',$p_bolSort?'true':'false');
	}

	/**
	 * 设置返回数据模式
	 * @param string $p_strWriterType
	 */
	function setWriterType($p_strWriterType='xml'){
		$this->_setWriterType($p_strWriterType);
	}

	/**
	 * 得到Search数据
	 * @return mix
	 */
	function getData(){
		$strRequestURL=$this->_buildURL();
		$strServerURL=$this->getServer();
		$strSelectURL=$strServerURL.'select?'.$strRequestURL;
		if($this->_bolDebug){	//APF::get_instance()->debug(get_class($this).'->Call: '.$strSelectURL);
		}
		/*apf_require_class('APF_Http_Client_Factory');
		$objCURL=APF_Http_Client_Factory::get_instance()->get_curl();*/
		$objCURL='';
		$objCURL->set_url($strSelectURL);
		$bolResult=$objCURL->execute();
		if($bolResult){
			$strResource=$objCURL->get_response_text();
			return json_decode($strResource,true);
		}else{
			trigger_error(get_class($this).'->Call: '.$strSelectURL.' failed.',E_USER_ERROR);
			return false;
		}
	}

	/**
	 * 解析SQL语句
	 * @param string $p_strSQL
	 * @todo 完善这个NB函数
	 */
	function parseSQL($p_strSQL){

	}

	/**
	 * 得到搜索服务器地址
	 * @return string
	 */
	abstract function getServer();

	/**
	 * 设置查询模式
	 * @param string $p_strQueryType
	 */
	private function _setQueryType($p_strQueryType){
		$this->_setQueryParameters('qt',$p_strQueryType);
	}

	/**
	 * 设置数据写入模式
	 * @param string $p_strWriterType
	 */
	private function _setWriterType($p_strWriterType){
		$this->_setQueryParameters('wt',$p_strWriterType);
	}

	/**
	 * 设置查询参数
	 * @param string $p_strField
	 * @param string $p_strValue
	 */
	private function _setQueryParameters($p_strField,$p_strValue){
		$this->_arrQueryParameters[$p_strField]=$p_strValue;
	}

	/**
	 * 添加查询参数
	 * @param string $p_strField
	 * @param string $p_strValue
	 */
	private function _addQueryParameters($p_strField,$p_strValue){
		if(isset($this->_arrQueryParameters[$p_strField])){
			if(is_array($this->_arrQueryParameters[$p_strField])){
				$this->_arrQueryParameters[$p_strField][]=$p_strValue;
			}else{
				$strTmp=$this->_arrQueryParameters[$p_strField];
				$this->_arrQueryParameters[$p_strField]=array( 
						$strTmp,
						$p_strValue 
				);
			}
		}else{
			$this->_arrQueryParameters[$p_strField]=$p_strValue;
		}
	}

	/**
	 * 根据权重,自动确认Q的字段
	 */
	private function _setQueryQ(){
		$intCntProportion=count($this->_arrAndParametersProportion);
		$intCntAndParameters=count($this->_arrAndParameters);
		$arrTmpAndParameters=array();
		for($i=0;$i<$intCntProportion;++$i){
			foreach($this->_arrAndParameters as $strField=>$arrCondition){
				if($this->_arrAndParametersProportion[$i]==$strField){
					$arrTmpAndParameters[]=array( 
							$strField,
							$arrCondition 
					);
				}
			}
		}
		$this->_arrAndParameters=$arrTmpAndParameters;
	}

	/**
	 * 生成请求的URL
	 * @return string
	 */
	private function _buildURL(){
		$intCntAndParameters=count($this->_arrAndParameters);
		if(0==$intCntAndParameters and NULL===$this->_arrOrParameters){
			trigger_error(__CLASS__.': no search condition.',E_USER_ERROR);
		}
		if(is_array($this->_arrOrParameters)){
			$this->setDismaxModel();
			$this->_setQueryParameters('q',urlencode($this->_arrOrParameters['KEYWORD']));
			$strOrURL='';
			$intCntOrField=count($this->_arrOrParameters['FIELD']);
			for($i=0;$i<$intCntOrField;++$i){
				$arrField=$this->_arrOrParameters['FIELD'][$i];
				$strOrURL.='+'.urlencode($arrField[0].'^'.$arrField[1]);
			}
			$strOrURL=substr($strOrURL,1);
			$this->_setQueryParameters('qf',$strOrURL);
			$intFQStart=0;
			$this->_setQueryQ();
		}else{
			$this->_setQueryQ();
			$this->_setQueryParameters('q',self::param2str($this->_arrAndParameters[0][0],$this->_arrAndParameters[0][1]));
			$intFQStart=1;
		}
		for($i=$intFQStart;$i<$intCntAndParameters;++$i){
			$this->_addQueryParameters('fq',self::param2str($this->_arrAndParameters[$i][0],$this->_arrAndParameters[$i][1]));
		}
		foreach($this->_arrQueryParameters as $strQKey=>$mixValue){
			if(is_array($mixValue)){
				foreach($mixValue as $strSubQKey){
					$strURL.='&'.$strQKey.'='.$strSubQKey;
				}
			}else{
				$strURL.='&'.$strQKey.'='.$mixValue;
			}
		}
		return substr($strURL,1);
	}

	/**
	 * 把搜索条件转换为搜索字符串
	 * @param string $p_strField
	 * @param array $p_arrParam
	 * @return string
	 */
	private static function param2str($p_strField,$p_arrParam){
		$strParam='';
		$intCnt=count($p_arrParam);
		for($i=0;$i<$intCnt;++$i){
			$strParam.=' OR '.$p_strField.':'.$p_arrParam[$i];
		}
		if(isset($strParam[1])){
			$strParam=substr($strParam,4);
		}
		return urlencode($strParam);
	}
}